package com.maimao.search.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.intern.InternUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
//import com.baidu.fsg.uid.impl.CachedUidGenerator;
import com.maimao.core.model.resp.PageResult;
import com.maimao.core.utils.DateUtils;
import com.maimao.model.goods.enums.GoodsCheckEnum;
import com.maimao.model.goods.log.GoodsCheck;
import com.maimao.model.goods.log.GoodsCheckInput;
import com.maimao.search.utils.EsUtil;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author MaoLin Wang
 * @date 2021/3/22 2:32 下午
 */
@Service
public class GoodsCheckService {
    public static final int GOODS_CHECK_ALL = -2;
    private Log log = LogFactory.get(GoodsCheckService.class);


    @Value("${maimao.es.goodsCheck.index}")
    private String index;
    @Value("${maimao.es.goodsCheck.type}")
    private String type;

    @Autowired
    private EsUtil esUtil;

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Autowired
    private DocService docService;


    public void saveOrUpdate(GoodsCheck goodsCheck) {
        //1.先检查是否存在goodsId待审核记录，如果存在，则失效处理
        checkExist(goodsCheck.getGoodsId());
        //2.添加新的记录
        this.save(goodsCheck);
    }

    public void save(GoodsCheck goodsCheck) {
        docService.createDoc(index, Long.valueOf(goodsCheck.getId()), JSON.toJSONString(goodsCheck), type);
    }

    public boolean update(GoodsCheck goodsCheck) {
        return docService.updateDoc(index, goodsCheck.getId(), JSON.toJSONString(goodsCheck), type);
    }

    /**
     * 如果已经存在待审核的goodsId记录，则失效处理
     *
     * @param goodsId 待审核的商品id
     * @return
     */
    private void checkExist(String goodsId) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder
                .must(QueryBuilders.termQuery("goodsId", goodsId))
                .must(QueryBuilders.termQuery("status", GoodsCheckEnum.WAITING.getCode()));
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
                .query(boolQueryBuilder);
        SearchRequest searchRequest = new SearchRequest(index)
                .types(type)
                .source(searchSourceBuilder);
        JSONArray jsonArray = new JSONArray();
        SearchResponse response = esUtil.search(searchRequest, jsonArray);
        if (response.getHits().totalHits > 0) {
            List<GoodsCheck> goodsChecks = jsonArray.toJavaList(GoodsCheck.class);
            if (!ObjectUtil.isEmpty(goodsChecks)) {
                //失效处理
                BulkRequest bulkRequest = new BulkRequest();
                bulkRequest.timeout(TimeValue.MINUS_ONE);
                for (GoodsCheck goodsCheck : goodsChecks) {
                    goodsCheck.setStatus(GoodsCheckEnum.NOT_VALID.getCode());
                    UpdateRequest updateRequest = new UpdateRequest(index, type, String.valueOf(goodsCheck.getId()))
                            .doc(JSON.toJSONString(goodsCheck), XContentType.JSON);
                    bulkRequest.add(updateRequest);
                }
                List<String> goodsCheckIds = goodsChecks.stream().map(GoodsCheck::getId).collect(Collectors.toList());
                try {
                    BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
                    if (bulkResponse.hasFailures()) {
                        log.error("bulk 失效商品审核记录失败,记录ids:{},原因:{}", goodsCheckIds, bulkResponse.buildFailureMessage());
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    log.error("bulk 失效商品审核记录失败,记录ids:{},原因:{}", goodsCheckIds, e.getMessage());

                }


            }
        }
    }

    /**
     * 条件查询审核记录
     *
     * @return PageResult<GoodsCheck>
     */
    public PageResult<GoodsCheck> query(GoodsCheckInput checkInput) {

        BoolQueryBuilder boolQueryBuilder = getBoolQueryBuilder(checkInput);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
                .from((checkInput.getPage() - 1) * checkInput.getSize())
                .size(checkInput.getSize())
                .query(boolQueryBuilder);
        SearchRequest searchRequest = new SearchRequest(index)
                .types(type)
                .source(searchSourceBuilder);
        JSONArray jsonArray = new JSONArray();
        SearchResponse response = esUtil.search(searchRequest, jsonArray);
        PageResult<GoodsCheck> pageResult = esUtil.getPageResult(jsonArray, GoodsCheck.class, response);
        return pageResult;

    }

    /**
     * 组合查询条件
     */
    private BoolQueryBuilder getBoolQueryBuilder(GoodsCheckInput checkInput) {
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
                .must(QueryBuilders.termQuery(GoodsCheck.SYS_USER_ID_FIELD, checkInput.getSysUserId()));
        if (ObjectUtil.isNotNull(checkInput.getStatus()) && !checkInput.getStatus().equals(GOODS_CHECK_ALL)) {
            boolQueryBuilder.must(QueryBuilders.termQuery(GoodsCheck.STATUS_FIELD, checkInput.getStatus()));
        }
        if (StrUtil.isNotEmpty(checkInput.getBrandId()) && Integer.valueOf(checkInput.getBrandId()) > 0) {
            boolQueryBuilder.must(QueryBuilders.termQuery(GoodsCheck.BRAND_ID_FIELD, checkInput.getBrandId()));
        }
        if (StrUtil.isNotEmpty(checkInput.getGoodsId())) {
            boolQueryBuilder.must(QueryBuilders.termQuery(GoodsCheck.GOODS_ID_FIELD, checkInput.getGoodsId()));
        }
        if (StrUtil.isNotEmpty(checkInput.getGoodsName())) {
            boolQueryBuilder.must(QueryBuilders.matchQuery(GoodsCheck.GOODS_NAME_FIELD, checkInput.getGoodsName()));
        }

        if (ObjectUtil.isNotNull(checkInput.getFromTime())) {
            boolQueryBuilder.must(
                    QueryBuilders.rangeQuery(GoodsCheck.DELIVERY_TIME)
                            .from(checkInput.getFromTime())
                            .to(ObjectUtil.isNull(checkInput.getEndTime()) ? DateUtils.now()
                                    : checkInput.getEndTime().compareTo(DateUtils.now()) > 0 ? DateUtils.now()
                                    : checkInput.getEndTime())
            );
        }
        return boolQueryBuilder;

    }
}
